/**
 * Copyright 2020 - 2023 the original author or Linlan authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.linlan.commons.core;

import java.util.HashMap;
import java.util.Map;

/**
 * The Return Code of Response to interaction.
 * <p>
 * This class represents the return code of a response. It extends {@link HashMap} to hold key - value pairs,
 * typically used to return a code and a message for an operation result.
 *
 * @author YourName (You can replace this with the actual author's name)
 * @version 1.0
 * @since 1.0
 */
public class Rcode extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    /**
     * Constructs a new Rcode instance. The default code is set to the value of {@link Status#HA_OK}.
     */
    public Rcode() {
        put("code", Status.HA_OK.code());
    }

    /**
     * Returns an Rcode instance with code 0 and message "SUCCESS".
     *
     * @return an instance of {@link Rcode} representing a successful operation.
     */
    public static Rcode ok() {
        return new Rcode().put("msg", "SUCCESS");
    }

    /**
     * Returns an Rcode instance with code 0 and a custom message.
     *
     * @param msg the custom message to be included in the response.
     * @return an instance of {@link Rcode} with the specified message.
     */
    public static Rcode ok(String msg) {
        Rcode r = new Rcode();
        r.put("msg", msg);
        return r;
    }

    /**
     * Returns an Rcode instance with code 0 and includes all key - value pairs from the given map.
     *
     * @param map a map containing additional output information.
     * @return an instance of {@link Rcode} with the content of the given map.
     */
    public static Rcode ok(Map<String, Object> map) {
        Rcode r = new Rcode();
        r.putAll(map);
        return r;
    }

    /**
     * Puts a key - value pair into the Rcode instance and returns the instance itself for method chaining.
     *
     * @param key   the key to be added.
     * @param value the value associated with the key.
     * @return the current instance of {@link Rcode}.
     */
    public Rcode put(String key, Object value) {
        super.put(key, value);
        return this;
    }

    /**
     * Returns an Rcode instance representing an error with code 500 and a default error message.
     *
     * @return an instance of {@link Rcode} representing an internal server error.
     */
    public static Rcode error() {
        return error(Status.HA_ERROR_500.code(), "未知异常，请联系管理员");
    }

    /**
     * Returns an Rcode instance representing a failure with code 1 and a custom error message.
     *
     * @param msg the custom error message.
     * @return an instance of {@link Rcode} with the specified error message.
     */
    public static Rcode error(String msg) {
        return error(Status.HA_FAIL.code(), msg);
    }

    /**
     * Returns an Rcode instance representing an error with a specified code and message.
     *
     * @param code the error code.
     * @param msg  the error message.
     * @return an instance of {@link Rcode} with the specified code and message.
     */
    public static Rcode error(int code, String msg) {
        Rcode r = new Rcode();
        r.put("code", code);
        r.put("msg", msg);
        return r;
    }

    /**
     * Enumeration of status codes used in the Rcode class.
     * <p>
     * Defines different status codes for successful operations, failures, and internal server errors.
     */
    public enum Status {
        /**
         * Represents a normal and successful status. The corresponding code is 0.
         */
        HA_OK(0),
        /**
         * Represents a failure status. The corresponding code is 1.
         */
        HA_FAIL(1),
        /**
         * Represents an error status, similar to an HTTP 500 error. The corresponding code is 500.
         */
        HA_ERROR_500(500);

        /**
         * The status code.
         */
        private Integer code;

        /**
         * Constructs a Status enum with the given code.
         *
         * @param code the status code.
         */
        Status(int code) {
            this.code = code;
        }

        /**
         * Retrieves the status code.
         *
         * @return the status code.
         */
        public Integer code() {
            return this.code;
        }
    }
}